package cn.zzq.aix.nativeinterface.schemeplay;

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.util.YailProcedure;
import gnu.expr.Language;
import gnu.mapping.Procedure;
import gnu.mapping.ProcedureN;
import kawa.standard.Scheme;

@DesignerComponent(nonVisible = true, //
		category = ComponentCategory.EXTENSION, //
		iconName = "images/extension.png", //
		description = "一个scheme引擎可以与本地java对象的直接交互，也可以直接与ai对象交互", //
		version = 1)
@SimpleObject(external = true)
public class SchemePlay extends AndroidNonvisibleComponent {
	private static Language scheme;

	public SchemePlay(ComponentContainer container) {
		super(container.$form());
		scheme = Scheme.getInstance("scheme");
	}

	@SimpleFunction(description = "执行无返回值的Scheme代码")
	public static void EvaluteWithoutReturn(String code) {
		Evalute(code);
	}

	@SimpleFunction(description = "执行Scheme代码")
	public static Object Evalute(String code) {
		try {
			return scheme.eval(code);
		} catch (Throwable e) {
			throw new RuntimeException("SchemePlay组件发生异常:\n" + e.getMessage());
		}
	}

	@SimpleFunction(description = "将ai的匿名过程转化为Scheme的过程")
	public static Object ToSchemeProcedure(final YailProcedure procedure) {
		return new ProcedureN() {
			@Override
			public Object applyN(Object[] arg0) throws Throwable {
				return procedure.call(arg0);
			}
		};
	}

	@SimpleFunction(description = "将Scheme的过程转化为ai的过程")
	public static YailProcedure ToAiProcedure(Object schemeProcedure) {
		return new YailProcedure((Procedure) schemeProcedure);
	}

	@SimpleFunction(description = "从scheme运行环境中读取变量")
	public static Object Get(String name) {
		return scheme.lookup(name);
	}

	@SimpleFunction(description = "将ai的数据传递至scheme运行环境")
	public static void Put(String name, Object object) {
		if (object instanceof YailProcedure) {
			scheme.defineFunction(name, ToSchemeProcedure((YailProcedure) object));
		} else {
			scheme.define(name, object);
		}
	}

}
